package com.ctvit.breadking.news.xfyun.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ctvit.breadking.news.core.solr.repository.SolrDocumentRepository;
import com.ctvit.breadking.news.task.pojo.entity.HttpLogEntity;
import com.ctvit.breadking.news.xfyun.service.MachineTranslationService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static com.ctvit.breadking.news.core.constant.CommonConstant.FIELD_CREATE_TIME;

@Slf4j
@Service
public class MachineTranslationServiceImpl implements MachineTranslationService {

    private static final String REQUEST_URL = "https://itrans.xf-yun.com/v1/its";
    // 控制台获取以下信息
    private static final String APP_ID = "797ca34b";
    private static final String API_SECRET = "YWM0MDc4MmZhOTc2NjM5ZWVlMzRlN2Yw";
    private static final String API_KEY = "891cf3a757d7c15bb4dadc858453cc7e";
    // 术语资源唯一标识，请根据控制台定义的RES_ID替换具体值，如不需术语可以不用传递此参数
    private static final String RES_ID = "g08g2b0x9m";
    // 源语种
    private static final String FROM="en";
    // 目标语种
    private static final String TO="cn";

    private static final Gson GSON = new Gson();

    private final SolrDocumentRepository solrDocumentRepository;

    public MachineTranslationServiceImpl(SolrDocumentRepository solrDocumentRepository) {
        this.solrDocumentRepository = solrDocumentRepository;
    }

    // 请求方法
    public String doRequest(String params) throws Exception {
        URL realUrl = new URL(buildRequetUrl());
        URLConnection connection = realUrl.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
        httpURLConnection.setDoInput(true);
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Content-type","application/json");
        OutputStream out = httpURLConnection.getOutputStream();

        log.info("params=>"+params.replaceAll(" ",""));
        out.write(params.getBytes());
        out.flush();
        InputStream is = null;
        try{
            is = httpURLConnection.getInputStream();
        }catch (Exception e){
            is = httpURLConnection.getErrorStream();
            throw new Exception("make request error:"+"code is "+httpURLConnection.getResponseMessage()+readAllBytes(is));
        }
        return readAllBytes(is);
    }
    // 处理请求URL，包含鉴权
    public String buildRequetUrl(){
        URL url = null;
        // 替换调schema前缀 ，原因是URL库不支持解析包含ws,wss schema的url
        String  httpRequestUrl = REQUEST_URL.replace("ws://", "http://").replace("wss://","https://" );
        try {
            url = new URL(httpRequestUrl);
            //获取当前日期并格式化
            SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
            format.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date = format.format(new Date());
            //String date="Thu, 18 Nov 2021 03:05:18 GMT";
            String host = url.getHost();
           /* if (url.getPort()!=80 && url.getPort() !=443){
                host = host +":"+String.valueOf(url.getPort());
            }*/
            StringBuilder builder = new StringBuilder("host: ").append(host).append("\n").//
                    append("date: ").append(date).append("\n").//
                    append("POST ").append(url.getPath()).append(" HTTP/1.1");
            Charset charset = Charset.forName("UTF-8");
            Mac mac = Mac.getInstance("hmacsha256");
            SecretKeySpec spec = new SecretKeySpec(API_SECRET.getBytes(charset), "hmacsha256");
            mac.init(spec);
            byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
            String sha = Base64.getEncoder().encodeToString(hexDigits);

            String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", API_KEY, "hmac-sha256", "host date request-line", sha);
            String authBase = Base64.getEncoder().encodeToString(authorization.getBytes(charset));
            return String.format("%s?authorization=%s&host=%s&date=%s", REQUEST_URL, URLEncoder.encode(authBase), URLEncoder.encode(host), URLEncoder.encode(date));
        } catch (Exception e) {
            throw new RuntimeException("assemble requestUrl error:"+e.getMessage());
        }
    }

    // 组装请求参数
    private String  buildParam(String text) {
        String param = "{"+
                "    \"header\": {"+
                "        \"app_id\": \""+ APP_ID +"\","+
                "        \"status\": 3,"+
                "        \"res_id\": \""+RES_ID+"\""+
                "    },"+
                "    \"parameter\": {"+
                "        \"its\": {"+
                "            \"from\": \""+FROM+"\","+
                "            \"to\": \""+TO+"\","+
                "            \"result\": {}"+
                "        }"+
                "    },"+
                "    \"payload\": {"+
                "        \"input_data\": {"+
                "            \"encoding\": \"utf8\","+
                "            \"status\": 3,"+
                "            \"text\": \""+Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8))+"\""+
                "        }"+
                "    }"+
                "}";
        return param;
    }
    // 读取流数据
    private String readAllBytes(InputStream is) throws IOException {
        byte[] b = new byte[1024];
        StringBuilder sb = new StringBuilder();
        int len = 0;
        while ((len = is.read(b)) != -1){
            sb.append(new String(b, 0, len, "utf-8"));
        }
        return sb.toString();
    }
    // JSON解析
    class JsonParse{
        Payload payload;
    }
    class Payload{
        Result result;
    }
    class Result{
        String text;
    }


    @Override
    public boolean translate(String text) {
        try {
            long requestTime=System.currentTimeMillis();
            String requestBody = buildParam(text);
            String responseBody = doRequest(requestBody);
            log.info("responseBody=>"+responseBody);
            long responseTime=System.currentTimeMillis();

            log.info("itrans.duration:[{}]", (responseTime - requestTime));

            SolrInputDocument solrDocument = assignHttpLogElement(HttpMethod.POST.name(), requestBody, responseBody, requestTime, responseTime);
            solrDocumentRepository.add(HttpLogEntity.COLLECTION_HTTP_LOG, solrDocument.getFieldValue(HttpLogEntity.FIELD_ID).toString(), solrDocument);

            JsonParse responseJsonParse = GSON.fromJson(responseBody, JsonParse.class);
            String textBase64Decode=new String(Base64.getDecoder().decode(responseJsonParse.payload.result.text), StandardCharsets.UTF_8.name());
            JSONObject jsonObject = JSON.parseObject(textBase64Decode);
            log.info("text字段Base64解码后=>"+jsonObject);
        } catch (Exception e) {
            log.error("请求科大翻译异常, text:[{}]", text, e);
        }
        return true;
    }

    private SolrInputDocument assignHttpLogElement(String requestMethod, String requestBody, String responseBody, long requestTime, long responseTime) {
        SolrInputDocument solrDocument = new SolrInputDocument();
        solrDocument.addField(HttpLogEntity.FIELD_ID, "itrans.xf-yun.com/v1/its_" + System.currentTimeMillis());
        solrDocument.addField(HttpLogEntity.FIELD_CODE, "itrans.xf-yun.com/v1/its");
        solrDocument.addField(HttpLogEntity.FIELD_NAME, "科大讯飞机器翻译");
        solrDocument.addField(HttpLogEntity.FIELD_URL, REQUEST_URL);
        solrDocument.addField(HttpLogEntity.FIELD_REQUEST_METHOD, requestMethod);
        solrDocument.addField(HttpLogEntity.FIELD_REQUEST_BODY, requestBody);
        solrDocument.addField(HttpLogEntity.FIELD_REQUEST_TIME, requestTime);
        solrDocument.addField(HttpLogEntity.FIELD_RESPONSE_BODY, responseBody);
        solrDocument.addField(HttpLogEntity.FIELD_RESPONSE_TIME, responseTime);
        solrDocument.addField(FIELD_CREATE_TIME, new Date());
        return solrDocument;
    }

}
